﻿using System;
using System.IO;
using System.Reflection;
using Microsoft.VisualBasic.ApplicationServices;
using MsSqlSpatial.Properties;
using MsSqlSpatial.Utility;
using YACLAP;

namespace MsSqlSpatial
{
	internal sealed class Program
	{
		private static void Main(string[] args)
		{
		    DisplayProductInfo();

		    using (ArgParser arg = new ArgParser(args, '-', '='))
		    {
		      if (String.Join("", args).Trim().Length == 0 || arg.Exists("help") || arg.Exists("h") || arg.Exists("?"))
		      {
		        DisplayHelp();
		      }
		      else
		      {
		        ConnectionOptions sqlServerConnection = new ConnectionOptions();
		        SqlServerOptions sqlServerOptions = new SqlServerOptions();

		        ExtractSqlServerArguments(arg, sqlServerConnection, sqlServerOptions);

		        if (arg.Exists("undeploy"))
		        {
		          Undeploy(sqlServerConnection);
		        }
		        else if (arg.Exists("deploy"))
		        {
		          Deploy(arg, sqlServerConnection);
		        }
		        else if (arg.Exists("import"))
		        {
		          bool appendRows = (0 == string.Compare(arg.GetValueOrDefault("append_rows", "false"), "true", true));
		          switch (arg["import"].Value.ToLower())
		          {
		            case "shp":
		              ImportShapefile(arg, sqlServerConnection, sqlServerOptions, appendRows);
		              break;
		            case "pgsql":
		              ImportPostGis(arg, sqlServerConnection, sqlServerOptions, appendRows);
		              break;
		          }
		        }
		        else if (arg.Exists("export"))
		        {
		          //string export = arg["export"].Value.ToLower();
		          Console.WriteLine("Export not implemented yet");
		        }
		        else
		        {
		          Console.WriteLine("Unknown command. Please, read usage instructions below.");
		          Console.WriteLine();
		          DisplayHelp();
		        }
		      }
#if DEBUG
				Console.WriteLine("Press any key to continue...");
				Console.ReadLine();
#endif
		    }
		  }

		private static void DisplayProductInfo()
		{
			AssemblyInfo assemblyInfo = new AssemblyInfo(Assembly.GetExecutingAssembly());
			Console.WriteLine(string.Format(
@"{0} (Build {1})
{2}
http://www.codeplex.com/MsSqlSpatial
",
assemblyInfo.Title,
assemblyInfo.Version.ToString(),
assemblyInfo.Copyright
));
		}

		private static void ExtractSqlServerArguments(YACLAP.ArgParser arg, ConnectionOptions sqlServerConnection, SqlServerOptions sqlServerOptions)
		{
			string server = arg.GetValueOrDefault("server", Settings.Default.server);
			string db = arg.GetValueOrDefault("db", Settings.Default.db);
			string login = arg["login"].Value;
			string password = arg["password"].Value;
			string schema = arg.GetValueOrDefault("schema", Settings.Default.schema);
			string table = arg["table"].Value;
			string column = arg.GetValueOrDefault("column", Settings.Default.column);
			string sridArgument = arg.GetValueOrDefault("srid", Settings.Default.srid);
			string type = arg.GetValueOrDefault("type", Settings.Default.type);
			bool userInstance = arg.Exists("user_instance") || Settings.Default.user_instance;
			bool attachAsFile = arg.Exists("attach_as_file") || Settings.Default.attach_as_file;

			int srid = Convert.ToInt32(sridArgument);

			sqlServerConnection.Server = server;
			sqlServerConnection.Database = db;
			sqlServerConnection.Login = login;
			sqlServerConnection.Password = password;
			sqlServerConnection.UserInstance = userInstance;
			sqlServerConnection.AttachAsFile = attachAsFile;

			sqlServerOptions.Schema = schema;
			sqlServerOptions.Table = table;
			sqlServerOptions.Column = column;
			sqlServerOptions.SRID = srid;
			sqlServerOptions.Subtype = type;
		}

		private static void Undeploy(ConnectionOptions sqlServerConnection)
		{
			Console.WriteLine(string.Format("Undeploying from database '{0}' at {1}:",
				sqlServerConnection.Database,
				sqlServerConnection.Server));
			Console.WriteLine();
			Command.Undeploy(sqlServerConnection);
			Console.WriteLine();
			Console.WriteLine("MsSqlSpatial undeployed.");
		}

		private static void Deploy(YACLAP.ArgParser arg, ConnectionOptions sqlServerConnection)
		{
			string deployPermissionArgument = arg.GetValueOrDefault("deploy_permission", Settings.Default.deploy_permission).Trim().ToUpper();
			DeployPermission deployPermission = (DeployPermission)Enum.Parse(typeof(DeployPermission), deployPermissionArgument.Replace("_", ""), true);
			Console.WriteLine(string.Format("Deploying to database '{0}' at {1}:",
				sqlServerConnection.Database,
				sqlServerConnection.Server));
			Console.WriteLine();
			Command.Deploy(sqlServerConnection, deployPermission);
			Console.WriteLine();
			Console.WriteLine("MsSqlSpatial deployed.");
		}

		private static void ImportShapefile(YACLAP.ArgParser arg, ConnectionOptions sqlServerConnection, SqlServerOptions sqlServerOptions, bool appendRows)
		{
			Console.WriteLine("Importing...");

			string filename = arg["shp_filename"].Value;
			TaskStats stats = Command.ImportShapefile(sqlServerConnection, sqlServerOptions, filename, appendRows);
			Console.WriteLine("{0} rows imported in {1} from shapefile '{2}'.",
				stats.RowsProcessed, 
				StoredProcedures.FormatElapsedTime(stats.ElapsedTime), 
				Path.GetFileName(filename));
		}

		private static void ImportPostGis(YACLAP.ArgParser arg, ConnectionOptions sqlServerConnection, SqlServerOptions sqlServerOptions, bool appendRows)
		{
			Console.WriteLine("Importing...");

			string server = arg.GetValueOrDefault("pgsql_server", Settings.Default.pgsql_server);
			string db = arg.GetValueOrDefault("pgsql_db", Settings.Default.pgsql_db);
			string login = arg.GetValueOrDefault("pgsql_login", Settings.Default.pgsql_login);
			string password = arg["pgsql_password"].Value;

			string schema = arg.GetValueOrDefault("pgsql_schema", Settings.Default.pgsql_schema);
			string table = arg["pgsql_table"].Value;
			string geometryColumn = arg.GetValueOrDefault("pgsql_geom_column", Settings.Default.pgsql_geom_column);
			string identifierColumn = arg.GetValueOrDefault("pgsql_oid_column", Settings.Default.pgsql_oid_column);

			ConnectionOptions postGisConnection = new ConnectionOptions();
			postGisConnection.Server = server;
			postGisConnection.Database = db;
			postGisConnection.Login = login;
			postGisConnection.Password = password;

			PostGisOptions postGisOptions = new PostGisOptions();
			postGisOptions.Schema = schema;
			postGisOptions.Table = table;
			postGisOptions.GeometryColumn = geometryColumn;
			postGisOptions.IdentifierColumn = identifierColumn;

			if (string.IsNullOrEmpty(sqlServerOptions.Table))
				sqlServerOptions.Table = postGisOptions.Table;

			TaskStats stats = Command.ImportPostGis(sqlServerConnection, postGisConnection, sqlServerOptions, postGisOptions, appendRows);

			Console.WriteLine("{0} rows imported in {1} from PostGIS table '{2}'.", stats.RowsProcessed, StoredProcedures.FormatElapsedTime(stats.ElapsedTime), postGisOptions.Table);
		}
		
		private static void DisplayHelp()
		{
			Stream resource = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("MsSqlSpatial.README.txt");
			Console.WriteLine(new StreamReader(resource).ReadToEnd());
		}
	}
}
